home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolfedit2 2.0.4 source.sit / WolfEdit2 2.0.4 Source / UMapPalette.p < prev    next >
Text File  |  1996-07-28  |  14KB  |  588 lines

  1. unit UMapPalette;
  2.  
  3. interface
  4.     uses
  5.         UMapCellsView;
  6.  
  7.     type
  8.  
  9.         TMapPalette = object(TMapCellsView)
  10.                 procedure IMapPalette (itsMapList: TMapListDoc);
  11.                 function CurrentCell: Point;
  12.                 procedure SelectCell (cell: Point);
  13.                 procedure GetCurrentCodeAndMask (var code, mask: MapCell);
  14.                 procedure GetCodeAndMask (cell: Point; var code, mask: MapCell);
  15.                 function GetCode (cell: Point): MapCell;
  16.                 function GetMask (cell: Point): MapCell;
  17.                 function SelectByCommand (cmdNumber: integer): boolean;
  18.                 procedure SelectByExample (example: MapCell);
  19.                 procedure TMapPalette.SetupPaletteMenus (curEncounter: integer);
  20.                 procedure DrawCell (cell: Point; r: Rect; var hilite: boolean);
  21.                 override;
  22.                 function TMapPalette.GetCellForDrawing (cell: Point): MapCell;
  23.                 override;
  24.                 procedure ChangeCellHilite (cell: Point; hilite: boolean);
  25.                 override;
  26.                 procedure Click (var e: EventInfo);
  27.                 override;
  28.                 procedure SetSelectionRect (newSel: Rect);
  29.                 override;
  30.                 procedure ImagesChanged;
  31.             end;
  32.  
  33.     procedure IUMapPalette;
  34.  
  35. implementation
  36.     uses
  37.         HexIO;
  38.  
  39.     const
  40.  
  41.         paletteWidth = 21;        {Number of columns in the palette.}
  42.                                         {The number of rows is dynamic.}
  43.  
  44.         paletteWidthLess1 = paletteWidth - 1;
  45.  
  46.     {Item types for palette initialisation resources}
  47.  
  48.         generalItem = 0;
  49.         wallItem = 1;
  50.         objectItem = 2;
  51.  
  52.     type
  53.  
  54.     {The palette table contains an entry for each cell of the palette.}
  55.  
  56.         PaletteTableEntry = record
  57.                 encounter: integer;                {Encounter available in}
  58.                 cmdNumber: integer;                {Associated menu command}
  59.             end;
  60.  
  61.         PaletteTableHandle = ^PaletteTablePtr;
  62.         PaletteTablePtr = ^PaletteTable;
  63.         PaletteTable = array[0..99, 0..paletteWidthLess1] of PaletteTableEntry;
  64.  
  65.     {Palette initialisation resource}
  66.  
  67.         SimplePALTItem = record
  68.                 code: integer;
  69.                 cmdNumber: integer;
  70.             end;
  71.  
  72.         GeneralPALTItem = packed record
  73.                 wall, obj, dir: 0..255;
  74.                 wallMask, objMask, dirMask: 0..255;
  75.                 cmdNumber: integer;
  76.             end;
  77.  
  78.         PALTHandle = ^PALTPtr;
  79.         PALTPtr = ^PALTRecord;
  80.         PALTRecord = record
  81.                 encounter: integer;
  82.                 case itemType : integer of
  83.                     wallItem, objectItem: (
  84.                             numSimpleItems: integer;
  85.                             simpleItems: array[1..99] of SimplePALTItem;
  86.                     );
  87.                     generalItem: (
  88.                             unused: integer;
  89.                             numGeneralItems: integer;
  90.                             generalItems: array[1..99] of GeneralPALTItem;
  91.                     );
  92.             end;
  93.  
  94.     {Table describing menu items which modify palette codes}
  95.  
  96.         TPaletteModifier = object
  97.                 fPMOD: PMODHandle;
  98.                 fState: integer;
  99.                 fNext: TPaletteModifier;
  100.                 procedure IPaletteModifier (pmod: PMODHandle);
  101.                 function TPaletteModifier.ModifyCell (var cell: MapCell): boolean;
  102.                 function TPaletteModifier.Yields (cell, example, mask: MapCell; var state: integer): boolean;
  103.                 procedure TPaletteModifier.SetupMenus (curEncounter: integer);
  104.                 function TPaletteModifier.DoMenuCommand (cmdNumber: integer): boolean;
  105.             end;
  106.  
  107.     var
  108.  
  109.         gNumPaletteItems: integer;        {Number of occupied cells}
  110.         gNumPaletteCells: integer;        {Total number of cells}
  111.         gPaletteWidth: integer;                {Number of cells wide}
  112.         gPaletteHeight: integer;            {Number of cells high}
  113.  
  114.         gMapPaletteCells: TMapCells;
  115.         gMapPaletteMasks: TMapCells;
  116.         gPaletteTable: PaletteTableHandle;
  117.         gPalModList: TPaletteModifier;
  118.  
  119. {------------------------- Unit Initialisation ----------------------------}
  120.  
  121.     function MakeMapCell (wall, obj, flags: integer): MapCell;
  122.     begin
  123.         MakeMapCell.wall := wall;
  124.         MakeMapCell.obj := obj;
  125.         MakeMapCell.flags := flags;
  126.         MakeMapCell.area := 0;
  127.     end;
  128.  
  129.     procedure IUMapPalette;
  130.  
  131.         procedure ForEachPALT (procedure ProcessPALT (h: PALTHandle));
  132.             var
  133.                 h: Handle;
  134.                 i: integer;
  135.         begin
  136.             i := 128;
  137.             while true do begin
  138.                     h := GetResource('PALT', i);
  139.                     if h = nil then
  140.                         exit(ForEachPALT);
  141.                     ProcessPALT(PALTHandle(h));
  142.                     ReleaseResource(h);
  143.                     i := i + 1;
  144.                 end;
  145.         end;
  146.  
  147.         function CountPaletteItems: integer;
  148.             var
  149.                 n: integer;
  150.  
  151.             procedure CountPALTItems (palt: PALTHandle);
  152.             begin
  153.                 case palt^^.itemType of
  154.                     wallItem, objectItem: 
  155.                         n := n + palt^^.numSimpleItems;
  156.                     generalItem: 
  157.                         n := n + palt^^.numGeneralItems;
  158.                 end;
  159.             end;
  160.  
  161.         begin {CountPaletteItems}
  162.             n := 0;
  163.             ForEachPALT(CountPALTItems);
  164.             CountPaletteItems := n;
  165.         end;
  166.  
  167.         procedure InstallPaletteItems;
  168.             var
  169.                 cell: Point;
  170.                 n: integer;
  171.                 enc: integer;
  172.  
  173.             procedure NextCell;
  174.             begin
  175.                 cell.h := cell.h + 1;
  176.                 if cell.h = gPaletteWidth then begin
  177.                         cell.h := 0;
  178.                         cell.v := cell.v + 1;
  179.                     end;
  180.                 n := n + 1;
  181.             end;
  182.  
  183.             procedure InstallItem (wall, obj, flags, wallMask, objMask, flagsMask, cmdNum: integer);
  184.             begin
  185.                 with gPaletteTable^^[cell.v, cell.h] do begin
  186.                         encounter := enc;
  187.                         cmdNumber := cmdNum;
  188.                     end;
  189.                 gMapPaletteCells.SetCell(cell, MakeMapCell(wall, obj, flags));
  190.                 gMapPaletteMasks.SetCell(cell, MakeMapCell(wallMask, objMask, flagsMask));
  191.                 NextCell;
  192.             end;
  193.  
  194.             procedure InstallSimpleItem (t: integer; var item: SimplePALTItem);
  195.             begin
  196.                 case t of
  197.                     wallItem: 
  198.                         InstallItem(item.code, 0, 0, $FF, $FF, 0, item.cmdNumber);
  199.                     objectItem: 
  200.                         InstallItem(0, item.code, 0, $FF, $FF, 0, item.cmdNumber);
  201.                 end;
  202.             end;
  203.  
  204.             procedure InstallGeneralItem (var item: GeneralPALTItem);
  205.             begin
  206.                 with item do
  207.                     InstallItem(wall, obj, dir, wallMask, objMask, dirMask, cmdNumber);
  208.             end;
  209.  
  210.             procedure InstallItemsFromPALT (palt: PALTHandle);
  211.                 var
  212.                     i, t: integer;
  213.             begin
  214.                 enc := palt^^.encounter;
  215.                 t := palt^^.itemType;
  216.                 case t of
  217.                     wallItem, objectItem: 
  218.                         for i := 1 to palt^^.numSimpleItems do
  219.                             InstallSimpleItem(t, palt^^.simpleItems[i]);
  220.                     generalItem: 
  221.                         for i := 1 to palt^^.numGeneralItems do
  222.                             InstallGeneralItem(palt^^.generalItems[i]);
  223.                 end;
  224.             end;
  225.  
  226.             procedure InstallEmptyItem;
  227.             begin
  228.                 InstallItem(0, 0, 0, 0, 0, 0, 0);
  229.             end;
  230.  
  231.         begin {InstallPaletteItems}
  232.             SetPt(cell, 0, 0);
  233.             n := 0;
  234.             ForEachPALT(InstallItemsFromPALT);
  235.             while n < gNumPaletteCells do
  236.                 InstallEmptyItem;
  237.         end;
  238.  
  239.         procedure CalcPaletteSize;
  240.         begin
  241.             gNumPaletteItems := CountPaletteItems;
  242.             gPaletteWidth := paletteWidth;
  243.             gPaletteHeight := (gNumPaletteItems + gPaletteWidth - 1) div gPaletteWidth;
  244.             gNumPaletteCells := gPaletteWidth * gPaletteHeight;
  245.         end;
  246.  
  247.         procedure AllocatePaletteTable;
  248.         begin
  249.             gPaletteTable := PaletteTableHandle(NewHandle(gNumPaletteCells * sizeof(PaletteTableEntry)));
  250.         end;
  251.  
  252.         procedure InitCellsAndMasks;
  253.             var
  254.                 r: Rect;
  255.         begin
  256.             SetRect(r, 0, 0, gPaletteWidth, gPaletteHeight);
  257.             new(gMapPaletteCells);
  258.             gMapPaletteCells.IMapCells(r);
  259.             new(gMapPaletteMasks);
  260.             gMapPaletteMasks.IMapCells(r);
  261.         end;
  262.  
  263.         procedure InitPalModList;
  264.             var
  265.                 p: TPaletteModifier;
  266.                 i: integer;
  267.         begin
  268.             gPalModList := nil;
  269.             for i := 1 to CountResources('PMOD') do begin
  270.                     new(p);
  271.                     p.IPaletteModifier(PMODHandle(GetIndResource('PMOD', i)));
  272.                 end;
  273.         end;
  274.  
  275.     begin {IUMapPalette}
  276.         CalcPaletteSize;
  277.         AllocatePaletteTable;
  278.         InitCellsAndMasks;
  279.         InstallPaletteItems;
  280.         InitPalModList;
  281.     end;
  282.  
  283. {---------------------------- Utilities ---------------------------}
  284.  
  285.     procedure ForEachCell (procedure ProcessCell (c: Point));
  286.         var
  287.             row, col: integer;
  288.             cell: Point;
  289.     begin
  290.         for row := 0 to gPaletteHeight - 1 do
  291.             for col := 0 to gPaletteWidth - 1 do begin
  292.                     SetPt(cell, col, row);
  293.                     ProcessCell(cell);
  294.                 end;
  295.     end;
  296.  
  297.     function GetCode (itemType: integer; var cell: MapCell): integer;
  298.     begin
  299.         case itemType of
  300.             wallItem: 
  301.                 GetCode := cell.wall;
  302.             objectItem: 
  303.                 GetCode := cell.obj;
  304.         end;
  305.     end;
  306.  
  307.     procedure SetCode (itemType: integer; var cell: MapCell; code: integer);
  308.     begin
  309.         case itemType of
  310.             wallItem: 
  311.                 cell.wall := code;
  312.             objectItem: 
  313.                 cell.obj := code;
  314.         end;
  315.     end;
  316.  
  317. {---------------------------- Palette Modifier ---------------------}
  318.  
  319.     procedure TPaletteModifier.IPaletteModifier (pmod: PMODHandle);
  320.     begin
  321.         fPMOD := pmod;
  322.         fState := 0;
  323.         fNext := gPalModList;
  324.         gPalModList := self;
  325.     end;
  326.  
  327.     function TPaletteModifier.ModifyCell (var cell: MapCell): boolean;
  328.         var
  329.             code: integer;
  330.     begin
  331.         with fPMOD^^ do begin
  332.                 code := GetCode(itemType, cell);
  333.                 if (code >= firstCode) & (code <= lastCode) then begin
  334.                         SetCode(itemType, cell, code + fPMOD^^.entries[fState].offset);
  335.                         ModifyCell := true;
  336.                     end
  337.                 else
  338.                     ModifyCell := false;
  339.             end;
  340.     end;
  341.  
  342.     function TPaletteModifier.Yields (cell, example, mask: MapCell; var state: integer): boolean;
  343.         var
  344.             cell2: MapCell;
  345.             i, code: integer;
  346.     begin
  347.         cell2 := cell;
  348.         with fPMOD^^ do begin
  349.                 code := GetCode(itemType, cell);
  350.                 for i := 0 to lastCmd - firstCmd do begin
  351.                         if (code >= firstCode) & (code <= lastCode) then begin
  352.                                 SetCode(itemType, cell2, code + entries[i].offset);
  353.                                 if EqualCode(cell2, AndCode(example, mask)) then begin
  354.                                         state := i;
  355.                                         Yields := true;
  356.                                         exit(Yields);
  357.                                     end;
  358.                             end;
  359.                     end;
  360.             end;
  361.         Yields := false;
  362.     end;
  363.  
  364.     procedure TPaletteModifier.SetupMenus (curEncounter: integer);
  365.         var
  366.             cmd: integer;
  367.     begin
  368.         with fPMOD^^ do begin
  369.                 for cmd := firstCmd to lastCmd do
  370.                     if curEncounter >= entries[cmd - firstCmd].encounter then
  371.                         EnableCmd(cmd);
  372.                 CheckCmd(firstCmd + fState, true);
  373.             end;
  374.     end;
  375.  
  376.     function TPaletteModifier.DoMenuCommand (cmdNumber: integer): boolean;
  377.     begin
  378.         with fPMOD^^ do
  379.             if (cmdNumber >= firstCmd) & (cmdNumber <= lastCmd) then begin
  380.                     fState := cmdNumber - firstCmd;
  381.                     DoMenuCommand := true;
  382.                 end
  383.             else
  384.                 DoMenuCommand := false;
  385.     end;
  386.  
  387.     procedure ModifyCell (var cell: MapCell);
  388.         var
  389.             p: TPaletteModifier;
  390.     begin
  391.         p := gPalModList;
  392.         while (p <> nil) & not p.ModifyCell(cell) do
  393.             p := p.fNext;
  394.     end;
  395.  
  396.     function ModifierYields (cell, example, mask: MapCell; var p: TPaletteModifier; var state: integer): boolean;
  397.     begin
  398.         p := gPalModList;
  399.         while (p <> nil) & not p.Yields(cell, example, mask, state) do
  400.             p := p.fNext;
  401.         ModifierYields := p <> nil;
  402.     end;
  403.  
  404.     procedure SetupModifierMenus (curEncounter: integer);
  405.         var
  406.             p: TPaletteModifier;
  407.     begin
  408.         p := gPalModList;
  409.         while p <> nil do begin
  410.                 p.SetupMenus(curEncounter);
  411.                 p := p.fNext;
  412.             end;
  413.     end;
  414.  
  415.     function DoModifierCommand (cmdNumber: integer): boolean;
  416.         var
  417.             p: TPaletteModifier;
  418.     begin
  419.         p := gPalModList;
  420.         while (p <> nil) & not p.DoMenuCommand(cmdNumber) do
  421.             p := p.fNext;
  422.         DoModifierCommand := p <> nil;
  423.     end;
  424.  
  425. {------------------------ TMapPalette Methods ------------------------}
  426.  
  427.     procedure TMapPalette.IMapPalette (itsMapList: TMapListDoc);
  428.     begin
  429.         IMapCellsView(gMapPaletteCells, [], itsMapList);
  430.         SetCellSize(fCellSize.h + 4, fCellSize.v + 4);
  431.         SetSelection(0, 0, 1, 1);
  432.     end;
  433.  
  434.     function TMapPalette.CurrentCell: Point;
  435.     begin
  436.         CurrentCell := fSelection.topLeft;
  437.     end;
  438.  
  439.     procedure TMapPalette.SelectCell (cell: Point);
  440.     begin
  441.         SetSelection(cell.h, cell.v, cell.h + 1, cell.v + 1);
  442.     end;
  443.  
  444.     procedure TMapPalette.GetCurrentCodeAndMask (var code, mask: MapCell);
  445.     begin
  446.         GetCodeAndMask(CurrentCell, code, mask);
  447.         ModifyCell(code);
  448.     end;
  449.  
  450.     procedure TMapPalette.GetCodeAndMask (cell: Point; var code, mask: MapCell);
  451.     begin
  452.         code := GetCode(cell);
  453.         mask := GetMask(cell);
  454.     end;
  455.  
  456.     function TMapPalette.GetCode (cell: Point): MapCell;
  457.     begin
  458.         GetCode := gMapPaletteCells.GetCell(cell);
  459.     end;
  460.  
  461.     function TMapPalette.GetMask (cell: Point): MapCell;
  462.     begin
  463.         GetMask := gMapPaletteMasks.GetCell(cell);
  464.     end;
  465.  
  466.     function TMapPalette.SelectByCommand (cmdNumber: integer): boolean;
  467.  
  468.         procedure TestTableEntry (cell: Point);
  469.         begin
  470.             if gPaletteTable^^[cell.v, cell.h].cmdNumber = cmdNumber then begin
  471.                     SetSelection(cell.h, cell.v, cell.h + 1, cell.v + 1);
  472.                     SelectByCommand := true;
  473.                     exit(SelectByCommand);
  474.                 end;
  475.         end;
  476.  
  477.     begin {TMapPalette.SelectByCommand}
  478.         ForEachCell(TestTableEntry);
  479.         SelectByCommand := DoModifierCommand(cmdNumber);
  480.     end;
  481.  
  482.     procedure TMapPalette.SelectByExample (example: MapCell);
  483.  
  484.         procedure TestCell (cell: Point);
  485.             var
  486.                 code, mask: MapCell;
  487.                 modifier: TPaletteModifier;
  488.                 state: integer;
  489.         begin
  490.             GetCodeAndMask(cell, code, mask);
  491.             if ModifierYields(code, example, mask, modifier, state) then begin
  492.                     SelectCell(cell);
  493.                     modifier.fState := state;
  494.                     exit(SelectByExample);
  495.                 end
  496.             else if EqualCode(code, AndCode(example, mask)) then begin
  497.                     SelectCell(cell);
  498.                     exit(SelectByExample);
  499.                 end;
  500.         end;
  501.  
  502.     begin {TMapPalette.SelectByExample}
  503.         ForEachCell(TestCell);
  504.     end;
  505.  
  506.     procedure TMapPalette.SetupPaletteMenus (curEncounter: integer);
  507.  
  508.         procedure SetupForCell (cell: Point);
  509.             var
  510.                 cmd: integer;
  511.         begin
  512.             if fMapList.ItemAvailable(GetCode(cell)) then
  513.                 with gPaletteTable^^[cell.v, cell.h] do
  514.                     if cmdNumber <> 0 then begin
  515.                             EnableCmd(cmdNumber);
  516.                             if EqualPt(cell, fSelection.topLeft) then
  517.                                 CheckCmd(cmdNumber, true);
  518.                         end;
  519.         end;
  520.  
  521.     begin {SetupPaletteMenus}
  522.         ForEachCell(SetupForCell);
  523.         SetupModifierMenus(curEncounter);
  524.     end;
  525.  
  526.     procedure TMapPalette.DrawCell (cell: Point; r: Rect; var hilite: boolean);
  527.         var
  528.             ri: Rect;
  529.     begin
  530.         EraseRect(r);
  531.         if fMapList.ItemAvailable(GetCode(cell)) then begin
  532.                 ri := r;
  533.                 InsetRect(ri, 2, 2);
  534.                 inherited DrawCell(cell, ri, hilite);
  535.             end
  536.         else begin
  537.                 PenNormal;
  538.                 ForeColor(blackColor);
  539.                 MoveTo(r.left, r.top);
  540.                 LineTo(r.right - 1, r.bottom - 1);
  541.                 MoveTo(r.right - 1, r.top);
  542.                 LineTo(r.left, r.bottom - 1);
  543.             end;
  544.     end;
  545.  
  546.     function TMapPalette.GetCellForDrawing (cell: Point): MapCell;
  547.         var
  548.             code: MapCell;
  549.     begin
  550.         code := inherited GetCellForDrawing(cell);
  551. {$IFC FALSE}
  552.         ModifyCell(code);
  553. {$ENDC}
  554.         GetCellForDrawing := code;
  555.     end;
  556.  
  557.     procedure TMapPalette.ChangeCellHilite (cell: Point; hilite: boolean);
  558.         var
  559.             r: Rect;
  560.     begin
  561.         Focus;
  562.         CellToRect(cell, r);
  563.         PenNormal;
  564.         PenSize(2, 2);
  565.         PenMode(patXor);
  566.         FrameRect(r);
  567.     end;
  568.  
  569.     procedure TMapPalette.Click (var e: EventInfo);
  570.     begin
  571.         inherited Click(e);
  572.         Update;
  573.     end;
  574.  
  575.     procedure TMapPalette.SetSelectionRect (newSel: Rect);
  576.     begin
  577.         if fMapList.ItemAvailable(GetCode(newSel.topLeft)) then
  578.             inherited SetSelectionRect(newSel);
  579.     end;
  580.  
  581.     procedure TMapPalette.ImagesChanged;
  582.     begin
  583.         Invalidate;
  584.         if not fMapList.ItemAvailable(GetCode(fSelection.topLeft)) then
  585.             SetSelection(0, 0, 1, 1);
  586.     end;
  587.  
  588. end.